'use strict';

const Service = require('egg').Service;
const tencentcloud = require('tencentcloud-sdk-nodejs');

class AiAuditService extends Service {
  /**
   * AI 智能审核游记
   * @param {number} id - 游记ID
   * @return {Object} 审核结果
   */
  async auditTravelNote(id) {
    const { ctx, service } = this;

    try {
      // 1. 获取游记详情（不需要 userId 参数用于审核）
      const result = await service.travelNote.getNoteDetail(id, null);
      if (!result.success) {
        return { success: false, message: result.message || '游记不存在' };
      }

      const note = result.data;
      if (!note) {
        return { success: false, message: '游记不存在' };
      }

      // 2. 检查游记状态
      if (note.status !== 'pending') {
        return { success: false, message: '只能审核待审核状态的游记' };
      }

      // 3. 进行 AI 审核
      const auditResults = {
        coverImage: await this._auditCoverImage(note.cover_image, note.title),
        title: await this._auditText(note.title, '标题'),
        description: await this._auditText(note.description, '简介'),
        content: await this._auditText(note.content, '内容'),
      };

      // 4. 综合判断
      const allPassed = Object.values(auditResults).every(r => r.passed);
      const failedReasons = Object.entries(auditResults)
        .filter(([, result]) => !result.passed)
        .map(([key, result]) => `${this._getFieldName(key)}: ${result.reason}`)
        .join('；');

      // 5. 更新游记状态
      const auditStatus = allPassed ? 'approved' : 'rejected';
      const auditReason = allPassed ? 'AI 自动审核通过' : `AI 审核未通过：${failedReasons}`;

      await service.travelNote.auditNote(id, auditStatus, auditReason);

      return {
        success: true,
        data: {
          noteId: id,
          status: auditStatus,
          reason: auditReason,
          details: auditResults,
        },
      };
    } catch (error) {
      ctx.logger.error(`AI 审核游记 ${id} 失败:`, error);
      return {
        success: false,
        message: error.message,
      };
    }
  }

  /**
   * 批量 AI 审核游记
   * @param {Array<number>} ids - 游记ID数组
   * @return {Object} 批量审核结果
   */
  async batchAuditTravelNotes(ids) {
    const results = {
      success: 0,
      failed: 0,
      details: [],
    };

    for (const id of ids) {
      try {
        const result = await this.auditTravelNote(id);
        if (result.success) {
          results.success++;
          results.details.push({
            id,
            success: true,
            status: result.data.status,
            reason: result.data.reason,
          });
        } else {
          results.failed++;
          results.details.push({
            id,
            success: false,
            error: result.message,
          });
        }
      } catch (error) {
        results.failed++;
        results.details.push({
          id,
          success: false,
          error: error.message,
        });
      }
    }

    return results;
  }

  /**
   * 审核文本内容（使用腾讯云内容安全）
   * @param {string} text - 文本内容
   * @param {string} fieldName - 字段名称
   * @return {Object} 审核结果
   */
  async _auditText(text, fieldName) {
    const { ctx, app } = this;

    if (!text || text.trim() === '') {
      return {
        passed: false,
        reason: `${fieldName}不能为空`,
        score: 0,
      };
    }

    // 去除 HTML 标签
    const plainText = text.replace(/<[^>]+>/g, '');

    // 基础规则检查
    const issues = [];

    // 1. 长度检查
    if (fieldName === '标题' && plainText.length < 5) {
      issues.push('标题过短（少于5个字符）');
    }
    if (fieldName === '内容' && plainText.length < 50) {
      issues.push('内容过短（少于50个字符）');
    }

    // 2. 本地敏感词检查（快速预检）
    const sensitiveWords = [
      '色情',
      '赌博',
      '毒品',
      '反动',
      '暴力',
      '恐怖',
      '违法',
      '欺诈',
    ];

    const foundSensitiveWords = sensitiveWords.filter(word =>
      plainText.toLowerCase().includes(word.toLowerCase())
    );

    if (foundSensitiveWords.length > 0) {
      return {
        passed: false,
        reason: `包含敏感词：${foundSensitiveWords.join('、')}`,
        score: 20,
      };
    }

    // 3. 垃圾内容检查
    const spamPatterns = [
      /(.)\1{10,}/, // 重复字符过多
      /[！!]{5,}/, // 过多感叹号
      /[？?]{5,}/, // 过多问号
    ];

    spamPatterns.forEach((pattern, index) => {
      if (pattern.test(text)) {
        const reasons = [
          '包含大量重复字符',
          '包含过多感叹号',
          '包含过多问号',
        ];
        issues.push(reasons[index]);
      }
    });

    // 如果有基础问题，直接返回
    if (issues.length > 0) {
      return {
        passed: false,
        reason: issues.join('；'),
        score: Math.max(0, 80 - issues.length * 20),
      };
    }

    // 4. 调用腾讯云内容安全审核
    try {
      const tencentResult = await this._tencentTextModeration(plainText);

      if (tencentResult.passed) {
        return {
          passed: true,
          reason: `${fieldName}内容符合规范`,
          score: tencentResult.score,
        };
      } else {
        return {
          passed: false,
          reason: `${fieldName}${tencentResult.reason}`,
          score: tencentResult.score,
        };
      }
    } catch (error) {
      ctx.logger.error('腾讯云文本审核失败:', error);
      // 如果腾讯云审核失败，降级为本地审核
      return {
        passed: true,
        reason: `${fieldName}内容符合规范（本地审核）`,
        score: 85,
      };
    }
  }

  /**
   * 腾讯云文本内容审核
   * @param {string} text - 文本内容
   * @return {Object} 审核结果
   */
  async _tencentTextModeration(text) {
    const { app } = this;
    const config = app.config.tencentCloud;

    // 检查配置
    if (!config.secretId || config.secretId === 'YOUR_SECRET_ID') {
      throw new Error('腾讯云 SecretId 未配置');
    }

    try {
      // 创建客户端
      const TmsClient = tencentcloud.tms.v20201229.Client;
      const client = new TmsClient({
        credential: {
          secretId: config.secretId,
          secretKey: config.secretKey,
        },
        region: config.region,
        profile: {
          httpProfile: {
            endpoint: 'tms.tencentcloudapi.com',
          },
        },
      });

      // 发起审核请求
      const params = {
        Content: Buffer.from(text).toString('base64'),
        BizType: config.cms.textModeration.bizType || '',
      };

      const response = await client.TextModeration(params);

      // 解析审核结果
      const { Suggestion, Label, Score } = response;

      // Suggestion: Pass（通过）、Review（人工审核）、Block（违规）
      if (Suggestion === 'Pass') {
        return {
          passed: true,
          reason: '内容健康',
          score: 95,
        };
      } else if (Suggestion === 'Block') {
        const labelMap = {
          Illegal: '违法违规',
          Porn: '色情内容',
          Abuse: '谩骂',
          Terror: '暴恐',
          Ad: '广告',
          Polity: '涉政',
        };
        const reason = labelMap[Label] || '内容不符合规范';
        return {
          passed: false,
          reason,
          score: Math.max(0, 100 - Score),
        };
      } else {
        return {
          passed: false,
          reason: '内容需要人工审核',
          score: 70,
        };
      }
    } catch (error) {
      throw error;
    }
  }

  /**
   * 腾讯云图片内容审核
   * @param {string} imageUrl - 图片URL
   * @return {Object} 审核结果
   */
  async _tencentImageModeration(imageUrl) {
    const { app } = this;
    const config = app.config.tencentCloud;

    // 检查配置
    if (!config.secretId || config.secretId === 'YOUR_SECRET_ID') {
      throw new Error('腾讯云 SecretId 未配置');
    }

    try {
      // 创建客户端
      const ImsClient = tencentcloud.ims.v20201229.Client;
      const client = new ImsClient({
        credential: {
          secretId: config.secretId,
          secretKey: config.secretKey,
        },
        region: config.region,
        profile: {
          httpProfile: {
            endpoint: 'ims.tencentcloudapi.com',
          },
        },
      });

      // 发起审核请求
      const params = {
        FileUrl: imageUrl,
        BizType: config.cms.imageModeration.bizType || '',
      };

      const response = await client.ImageModeration(params);

      // 解析审核结果
      const { Suggestion, Label, Score } = response;

      if (Suggestion === 'Pass') {
        return {
          passed: true,
          reason: '图片健康',
          score: 95,
        };
      } else if (Suggestion === 'Block') {
        const labelMap = {
          Illegal: '违法违规',
          Porn: '色情图片',
          Abuse: '谩骂',
          Terror: '暴恐',
          Ad: '广告',
          Polity: '涉政',
        };
        const reason = labelMap[Label] || '图片不符合规范';
        return {
          passed: false,
          reason,
          score: Math.max(0, 100 - Score),
        };
      } else {
        return {
          passed: false,
          reason: '图片需要人工审核',
          score: 70,
        };
      }
    } catch (error) {
      throw error;
    }
  }

  /**
   * 审核封面图片
   * @param {string} imageUrl - 图片URL
   * @param {string} title - 游记标题
   * @return {Object} 审核结果
   */
  async _auditCoverImage(imageUrl, title) {
    const { ctx } = this;

    // 简单的封面审核规则
    if (!imageUrl || imageUrl.trim() === '') {
      return {
        passed: false,
        reason: '缺少封面图片',
        score: 0,
      };
    }

    // 检查图片URL格式
    const imageUrlPattern = /^https?:\/\/.+\.(jpg|jpeg|png|gif|webp)$/i;
    if (!imageUrlPattern.test(imageUrl)) {
      return {
        passed: false,
        reason: '封面图片格式不正确',
        score: 30,
      };
    }

    // 调用腾讯云图片审核
    try {
      const tencentResult = await this._tencentImageModeration(imageUrl);

      if (tencentResult.passed) {
        return {
          passed: true,
          reason: '封面图片符合规范',
          score: tencentResult.score,
        };
      } else {
        return {
          passed: false,
          reason: `封面图片${tencentResult.reason}`,
          score: tencentResult.score,
        };
      }
    } catch (error) {
      ctx.logger.error('腾讯云图片审核失败:', error);
      return {
        passed: true,
        reason: '封面图片符合规范（本地审核）',
        score: 85,
      };
    }
  }

  /**
   * AI 智能审核旅行计划
   * @param {number} id - 旅行计划ID
   * @return {Object} 审核结果
   */
  async auditTravelPlan(id) {
    const { ctx, service } = this;

    try {
      // 1. 获取旅行计划详情
      const plan = await service.travelPlan.getById(id);
      if (!plan) {
        return { success: false, message: '旅行计划不存在' };
      }

      // 2. 检查状态
      if (plan.status !== 'pending') {
        return { success: false, message: '只能审核待审核状态的旅行计划' };
      }

      // 3. 进行 AI 审核
      const auditResults = {
        title: await this._auditText(plan.title, '标题'),
        description: await this._auditText(plan.description, '描述'),
      };

      // 审核封面图片（如果有）
      if (plan.coverImage) {
        auditResults.coverImage = await this._auditCoverImage(plan.coverImage, plan.title);
      }

      // 4. 综合判断
      const allPassed = Object.values(auditResults).every(r => r.passed);
      const failedReasons = Object.entries(auditResults)
        .filter(([, result]) => !result.passed)
        .map(([key, result]) => `${this._getFieldName(key)}: ${result.reason}`)
        .join('；');

      // 5. 更新旅行计划状态
      const auditStatus = allPassed ? 'approved' : 'rejected';
      const auditReason = allPassed ? 'AI 自动审核通过' : `AI 审核未通过：${failedReasons}`;

      await service.travelPlan.auditPlan(id, auditStatus, auditReason);

      return {
        success: true,
        data: {
          planId: id,
          status: auditStatus,
          reason: auditReason,
          details: auditResults,
        },
      };
    } catch (error) {
      ctx.logger.error(`AI 审核旅行计划 ${id} 失败:`, error);
      return {
        success: false,
        message: error.message,
      };
    }
  }

  /**
   * 批量 AI 审核旅行计划
   * @param {Array<number>} ids - 旅行计划ID数组
   * @return {Object} 批量审核结果
   */
  async batchAuditTravelPlans(ids) {
    const results = {
      success: 0,
      failed: 0,
      details: [],
    };

    for (const id of ids) {
      try {
        const result = await this.auditTravelPlan(id);
        if (result.success) {
          results.success++;
          results.details.push({
            id,
            success: true,
            status: result.data.status,
            reason: result.data.reason,
          });
        } else {
          results.failed++;
          results.details.push({
            id,
            success: false,
            error: result.message,
          });
        }
      } catch (error) {
        results.failed++;
        results.details.push({
          id,
          success: false,
          error: error.message,
        });
      }
    }

    return results;
  }

  /**
   * 获取字段中文名称
   * @param {string} field - 字段名
   * @return {string} 中文名称
   */
  _getFieldName(field) {
    const fieldMap = {
      coverImage: '封面图片',
      title: '标题',
      description: '简介',
      content: '内容',
    };
    return fieldMap[field] || field;
  }
}

module.exports = AiAuditService;

